import express from 'express';
import puppeteer from 'puppeteer';
import path from 'path';
import fs from 'fs/promises';

const app = express();
app.use(express.json());

// Create storage directory if it doesn't exist
const storagePath = path.join(__dirname, '../storage');
fs.mkdir(storagePath, { recursive: true }).catch(console.error);

// Validate URL function
function isValidUrl(urlString: string): boolean {
  try {
    new URL(urlString);
    return true;
  } catch (err) {
    return false;
  }
}

// Routes
app.post('/api/crawl', async (req, res) => {
  try {
    const { url } = req.body;

    // Validate URL
    if (!url) {
      return res.status(400).json({ error: 'URL is required' });
    }

    if (!isValidUrl(url)) {
      return res.status(400).json({ error: 'Invalid URL format' });
    }

    console.log(`Crawling URL: ${url}`);

    const browser = await puppeteer.launch({
      headless: "new",
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu'
      ]
    });

    try {
      const page = await browser.newPage();

      // Set viewport
      await page.setViewport({
        width: 1920,
        height: 1080
      });

      // Navigate to URL with error handling
      try {
        await page.goto(url, {
          waitUntil: 'networkidle0',
          timeout: 30000
        });
      } catch (navError: any) {
        throw new Error(`Failed to navigate to ${url}: ${navError.message}`);
      }

      // Get page content
      let content: string;
      let title: string;
      try {
        content = await page.content();
        title = await page.title();
      } catch (contentError: any) {
        throw new Error(`Failed to get page content: ${contentError.message}`);
      }

      // Save the content
      const timestamp = Date.now();
      const fileName = `${timestamp}-${new URL(url).hostname}.html`;
      const filePath = path.join(storagePath, fileName);

      try {
        await fs.writeFile(filePath, content);
      } catch (writeError: any) {
        throw new Error(`Failed to save content: ${writeError.message}`);
      }

      res.json({
        title,
        url,
        savedAs: fileName,
        timestamp
      });
    } finally {
      await browser.close();
    }
  } catch (err) {
    const error = err as Error;
    console.error('Crawl error:', error);
    res.status(500).json({
      error: error.message,
      details: error.stack
    });
  }
});

// Start server
const PORT = Number(process.env.PORT) || 8080;
const HOST = '0.0.0.0';
app.listen(PORT, HOST, () => {
  console.log(`Server is running on http://${HOST}:${PORT}`);
});